package com.zhang.gmall.util

import com.zhang.gmall.bean.{DauInfo, PageLog}

import java.lang.reflect.{Field, Method, Modifier}
import scala.util.control.Breaks

/**
 * @title: 对象属性copy工具
 * @author: zhang
 * @date: 2022/3/24 16:40 
 */
object MyBeanUtil {

  /**
   * 将srcObj中的属性的值拷贝到destObj对应主题上
   *
   * @param srcObj
   * @param destObj
   */
  def copyProperties(srcObj: AnyRef, destObj: AnyRef): Unit = {
    if (srcObj == null || destObj == null) {
      return
    }
    //获取srcObj中所有的属性
    val srcFields: Array[Field] = srcObj.getClass.getDeclaredFields
    //拷贝每个属性
    //依赖对象的get 和 set方法
    //Scala get:fieldname(),set():fieldname_$eq(参数类型)
    for (srcField <- srcFields) {
      Breaks.breakable {
        val getMethodName: String = srcField.getName
        val setMethodName: String = srcField.getName + "_$eq"
        //从srcObj中获取get方法
        val getMethod: Method = srcObj.getClass.getDeclaredMethod(getMethodName)
        //重destObj中获取set方法
        val setMethod: Method =
          try {
            destObj.getClass.getDeclaredMethod(setMethodName, srcField.getType)
          } catch {
            // NoSuchMethodException
            case ex: Exception => Breaks.break()
          }

        //忽略val属性
        val destField: Field = destObj.getClass.getDeclaredField(srcField.getName)
        if (destField.getModifiers.equals(Modifier.FINAL)) {
          Breaks.break()
        }
        //调用get方法获取到srcObj属性的值， 再调用set方法将获取到的属性值赋值给destObj的属性
        setMethod.invoke(destObj, getMethod.invoke(srcObj))
      }
    }
  }
}
